package gnss

import (
	"bytes"
	"fmt"
	"sort"
	"strconv"
)

type RinexHeader struct {
	CHeader   []byte
	GHeader   []byte
	GloHeader []byte
	EHeader   []byte
	JHeader   []byte // QZSS
}

func NewRinexHeader() *RinexHeader {
	rval := &RinexHeader{
		CHeader:   make([]byte, 0, MAX_SIGNA_N),
		GHeader:   make([]byte, 0, MAX_SIGNA_N),
		GloHeader: make([]byte, 0, MAX_SIGNA_N),
		EHeader:   make([]byte, 0, MAX_SIGNA_N),
		JHeader:   make([]byte, 0, MAX_SIGNA_N),
	}
	return rval
}

func (this *RinexHeader) checkSearchSign(v []byte, sign byte) bool {
	for i := 0; i < len(v); i++ {
		if v[i] == sign {
			return true
		}
	}
	return false
}

func (this *RinexHeader) innerPrintSignHeader(signHeader []byte, nsys byte) string {
	str := ""

	aHeader := signHeader
	l := len(aHeader)
	//logger.Debug(l, ":", aHeader)
	if l > 0 {
		l = l * 4 // C(伪距), L(相位), D(多普勒), S(信号强度) 观测值类型

		str += GNSS_SYS_RINEX_CHAR[nsys]
		str += "   "

		if l < 10 {
			str += " "
		}
		str += strconv.FormatInt(int64(l), 10)
		str += " "
		strHeaders := make([]string, l, l)
		j := 0
		for i := 0; i < len(aHeader); i++ {
			isign := aHeader[i]
			if isign > MAX_SIGNA_N {
				strHeaders[j] = "CER"
				j += 1
				strHeaders[j] = "LER"
				j += 1
				strHeaders[j] = "DER"
				j += 1
				strHeaders[j] = "SER"
				j += 1
			} else {
				s := GetSignCode(isign, nsys)
				if len(s) == 0 {
					s = fmt.Sprintf("%d", isign)
				}
				strHeaders[j] = "C" + s
				j += 1
				strHeaders[j] = "L" + s
				j += 1
				strHeaders[j] = "D" + s
				j += 1
				strHeaders[j] = "S" + s
				j += 1
			}
		}

		//logger.Debug("j:", j, " ", len(strHeaders), ":", strHeaders)
		j = 7
		for i := 0; i < len(strHeaders); i++ {
			str += strHeaders[i] + " "
			j = j + 4
			if (i+1)%13 == 0 {
				str += " SYS / # / OBS TYPES\n       "
				j = 7
			}
		}

		j = (59 - j)
		if j > 0 {
			str += string(bytes.Repeat([]byte(" "), j))
			str += " SYS / # / OBS TYPES\n"
		}
	}

	return str

}

func (this *RinexHeader) PrintSignHeader() string {
	str := this.innerPrintSignHeader(this.CHeader, SYS_BD)
	str += this.innerPrintSignHeader(this.GHeader, SYS_GPS)
	str += this.innerPrintSignHeader(this.GloHeader, SYS_GLO)
	str += this.innerPrintSignHeader(this.EHeader, SYS_GAL)
	str += this.innerPrintSignHeader(this.JHeader, SYS_QZS)
	return str
}

func (this *RinexHeader) CheckAddMsmHeader(h *RtcmMsmHeader) bool {
	up := false
	var k byte
	for k = 0; k < h.SigN; k++ {
		sigi := h.Sigs[k]
		if this.CheckAddSign(h.Sys, sigi) {
			up = true
		}
	}
	return up
}

func (this *RinexHeader) CheckAddSign(nsys byte, sign byte) bool {
	if nsys == SYS_BD {
		if this.checkSearchSign(this.CHeader, sign) {
			return false
		}
		this.CHeader = append(this.CHeader, sign)
		return true
	} else if nsys == SYS_GPS {
		if this.checkSearchSign(this.GHeader, sign) {
			return false
		}
		this.GHeader = append(this.GHeader, sign)
		return true
	} else if nsys == SYS_GAL {
		if this.checkSearchSign(this.EHeader, sign) {
			return false
		}
		this.EHeader = append(this.EHeader, sign)
		return true
	} else if nsys == SYS_GLO {
		if this.checkSearchSign(this.GloHeader, sign) {
			return false
		}
		this.GloHeader = append(this.GloHeader, sign)
		return true
	} else if nsys == SYS_QZS {
		if this.checkSearchSign(this.JHeader, sign) {
			return false
		}
		this.JHeader = append(this.JHeader, sign)
		return true
	}
	return false
}

func (this *RinexHeader) SortSign(nsys byte) {
	if nsys == SYS_BD {
		sort.Slice(this.CHeader, func(i, j int) bool {
			return this.CHeader[i] < this.CHeader[j]
		})
	} else if nsys == SYS_GPS {
		sort.Slice(this.GHeader, func(i, j int) bool {
			return this.GHeader[i] < this.GHeader[j]
		})
	} else if nsys == SYS_GAL {
		sort.Slice(this.EHeader, func(i, j int) bool {
			return this.EHeader[i] < this.EHeader[j]
		})
	} else if nsys == SYS_GLO {
		sort.Slice(this.GloHeader, func(i, j int) bool {
			return this.GloHeader[i] < this.GloHeader[j]
		})
	}

}
